package com.schezhi.link.auth.aop;

import com.c39.cloud.rbac.model.auth.AuthStaffVO;
import com.cqfan.cloud.framework.base.context.ApplicationContextProvider;
import com.cqfan.cloud.framework.global.LogicI18nException;
import com.schezhi.link.auth.constant.AuthResultCodeEnum;
import com.schezhi.link.auth.model.UserAuthModel;
import com.schezhi.link.auth.session.SessionTemplate;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;

/**
 * @Author: JiaLing.Fan
 * @Date: 2022/11/28 22:03
 * @Description:
 */
@Slf4j
public class UserAuthInterceptor implements HandlerInterceptor {


    /**
     * 访问控制器方法前执行
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        String accessToken = request.getHeader("accessToken");
        String accessVersion = request.getHeader("accessVersion");
        String requestURI = request.getRequestURI();

        log.info("请求拦截 - URI: {}", requestURI);

        // 1. 令牌校验
        if (StringUtils.isEmpty(accessToken)) {
            log.warn("令牌为空 - URI: {}", requestURI);
            throw new LogicI18nException(AuthResultCodeEnum.TOKEN_EMPTY.getCode(),
                    AuthResultCodeEnum.TOKEN_EMPTY.getMsg());
        }

        // 2. 获取会话信息
        SessionTemplate<UserAuthModel> sessionTemplate = ApplicationContextProvider
                .applicationContext.getAutowireCapableBeanFactory().getBean(SessionTemplate.class);
        UserAuthModel userAuthModel = sessionTemplate.getSign(accessToken);
        if (userAuthModel == null) {
            log.warn("会话信息不存在 - Token: {}", accessToken);
            throw new LogicI18nException(AuthResultCodeEnum.TOKEN_INVALID.getCode(),
                    AuthResultCodeEnum.TOKEN_INVALID.getMsg());
        }

        // 3. 版本校验
        validateVersion(accessVersion, userAuthModel);

        // 4. 令牌匹配校验
        if (!accessToken.equals(userAuthModel.getAccessToken())) {
            log.warn("令牌不匹配 - User: {}, URI: {}", userAuthModel.getRealName(), requestURI);
            throw new LogicI18nException(AuthResultCodeEnum.TOKEN_MISMATCH.getCode(),
                    AuthResultCodeEnum.TOKEN_MISMATCH.getMsg());
        }

        // 5. 接口权限校验
        if (!hasInterfacePermission(userAuthModel, requestURI)) {
            log.warn("接口权限不足 - User: {}, URI: {}", userAuthModel.getRealName(), requestURI);
            throw new LogicI18nException(AuthResultCodeEnum.USER_INSUFFICIENT_PERMISSION.getCode(),
                    AuthResultCodeEnum.USER_INSUFFICIENT_PERMISSION.getMsg());
        }

        log.debug("权限校验通过 - User: {}, URI: {}", userAuthModel.getRealName(), requestURI);
        return true;
    }

    /**
     * 版本校验
     */
    private void validateVersion(String accessVersion, UserAuthModel userAuthLink) {
        if (!NumberUtils.isParsable(accessVersion)) {
            return;
        }

        int version = Integer.parseInt(accessVersion);
        if (version < userAuthLink.getVersion()) {
            log.info("权限版本需要升级 - Current: {}, Required: {}", version, userAuthLink.getVersion());
            throw new LogicI18nException(AuthResultCodeEnum.USER_VERSION_UPGRADE.getCode(),
                    AuthResultCodeEnum.USER_VERSION_UPGRADE.getMsg());
        }
    }

    /**
     * 接口权限校验
     */
    private boolean hasInterfacePermission(UserAuthModel userAuthModel, String requestURI) {
        List<String> permissions = userAuthModel.getInterfacePermissions();
        if (CollectionUtils.isEmpty(permissions)) {
            return false;
        }

        // 支持通配符匹配，如 /api/**
        return permissions.stream()
                .anyMatch(permission -> matchPermission(permission, requestURI));
    }

    /**
     * 权限路径匹配（支持通配符）
     */
    private boolean matchPermission(String permission, String requestURI) {
        if (permission.endsWith("/**")) {
            String prefix = permission.substring(0, permission.length() - 3);
            return requestURI.startsWith(prefix);
        }
        return permission.equals(requestURI);
    }

    /**
     * 访问控制器方法后执行
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
    }

    /**
     * postHandle方法执行完成后执行，一般用于释放资源
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {

        SessionTemplate<AuthStaffVO> sessionTemplate = ApplicationContextProvider.applicationContext.getAutowireCapableBeanFactory().getBean(SessionTemplate.class);
        sessionTemplate.currentThreadremove();
    }


}
